#ifndef __WHIMSY_DATATYPE_HPP__SHANHAOBO_19800429__
#define __WHIMSY_DATATYPE_HPP__SHANHAOBO_19800429__

#include "./WhimsyDataTypeBase.hpp"

namespace Whms
{
    namespace Rot
    {
        struct Type : public ::Whms::IntVec3::Type
        {
            typedef ::Whms::IntVec3::Type tSuper;

            Type()
            {}
            Type(const tElement& InX, const tElement& InY, const tElement& InZ) : tSuper(InX, InY, InZ)
            {}
            Type(const tElement& InEle) : tSuper(InEle)
            {}
            Type(const tSuper& InOther) : tSuper(InOther)
            {}

            ::Whms::Void::Type ToVec3Dir(::Whms::Vec3::Out OutVec3) const
            {
                OutVec3.x = ::Wiz::Cast::Static<::Whms::Real::Type>(x);
                OutVec3.y = ::Wiz::Cast::Static<::Whms::Real::Type>(y);
                OutVec3.z = ::Wiz::Cast::Static<::Whms::Real::Type>(z);

                OutVec3.Normalize();
            }
        };
        WIZ_DECLARE(::Whms::Rot::Type);
    } /// end of namespace Rot

    namespace Force
    {
        struct Type
        {
            ::Whms::Vec3::Type  m_Direction;
            ::Whms::Real::Type  m_Coefficient;
        };
        WIZ_DECLARE(::Whms::Force::Type);
    } /// end of namespace Force

    namespace MinMax
    {
        template<class ElementT>
        struct Type
        {
            ::Whms::Bool::Type   m_Valid;
            ElementT            m_Min;
            ElementT            m_Max;
        };
    } /// end of namespace MinMax

    namespace RealMinMax
    {
        typedef ::Whms::MinMax::Type<::Whms::Real::Type> Type;
        WIZ_DECLARE(::Whms::RealMinMax::Type);
    } /// end of namespace RealMinMax


    namespace ARGB
    {
        WIZ_DECLARE(::Wiz::ARGB::Type);
    } /// end of namespace ARGB
    namespace Color
    {
        WIZ_DECLARE(::Wiz::Color::Type);
        static const ::Whms::Color::Type Zero  = ::Wiz::Color::Zero;
        static const ::Whms::Color::Type Black = ::Wiz::Color::Black;
        static const ::Whms::Color::Type White = ::Wiz::Color::White;
        static const ::Whms::Color::Type Red   = ::Wiz::Color::Red;
        static const ::Whms::Color::Type Green = ::Wiz::Color::Green;
        static const ::Whms::Color::Type Blue  = ::Wiz::Color::Blue;
    } /// end of namespace Color
    ///==============================================================///
    namespace PackedPosition
    {
        struct Type
        {
            typedef ::Whms::UInt::Type tElement;
            enum
            {
                eCount = 1,
            };
            union
            {
                tElement        xyz;
                tElement        e[eCount];
            };

            Type(::Whms::Vec3::In InPos)
            {
                Pack(InPos);
            }

            ::Whms::Void::Type Pack(::Whms::Vec3::In InPos)
            {

            }

            ::Whms::Void::Type Unpack(::Whms::Vec3::Out OutPos)
            {

            }

            template<class OutT>
            ::Wiz::Size::Type CopyTo(OutT* DestPtr) const
            {
                WIZ_ASSERT(sizeof(this->e) == sizeof(tElement) * eCount);

                return ::Wiz::Memory::CopySrcStd(DestPtr, this->e, eCount);
            }
            template<class InT>
            ::Wiz::Size::Type CopyFrom(const InT* SrcPtr) const
            {
                WIZ_ASSERT(sizeof(this->e) == sizeof(tElement) * eCount);

                return ::Wiz::Memory::CopyDestStd(this->e, SrcPtr, eCount);
            }
        };
        WIZ_DECLARE(::Whms::PackedPosition::Type);
    } /// end of namespace PackedPosition
    namespace PackedDirection
    {
        struct Type
        {
            typedef ::Wiz::UInt16::Type tElement;
            enum
            {
                eCount = 2,
            };
            union
            {
                struct  
                {
                    tElement    X;
                    tElement    Y;
                };
                tElement        e[eCount];
            };

            Type(::Whms::Vec3::In InOrient)
            {
                Pack(InOrient);
            }

            ::Whms::Void::Type Pack(::Whms::Vec3::In InOrient)
            {

            }

            ::Whms::Void::Type Unpack(::Whms::Vec3::Out OutOrient)
            {

            }

            template<class OutT>
            ::Wiz::Size::Type CopyTo(OutT* DestPtr) const
            {
                WIZ_ASSERT(sizeof(this->e) == sizeof(tElement) * eCount);

                return ::Wiz::Memory::CopySrcStd(DestPtr, this->e, eCount);
            }
            template<class InT>
            ::Wiz::Size::Type CopyFrom(const InT* SrcPtr) const
            {
                WIZ_ASSERT(sizeof(this->e) == sizeof(tElement) * eCount);

                return ::Wiz::Memory::CopyDestStd(this->e, SrcPtr, eCount);
            }
        };
        WIZ_DECLARE(::Whms::PackedDirection::Type);
    } /// end of namespace PackedNormal
    namespace PackedTexCoord
    {
        struct Type
        {
            typedef ::Wiz::UInt16::Type tElement;
            enum
            {
                eCount = 2,
            };
            union
            {
                struct  
                {
                    tElement    U;
                    tElement    V;
                };
                tElement        e[eCount];
            };

            Type(::Whms::Vec2::In InTexCoord)
            {
                Pack(InTexCoord);
            }

            ::Whms::Void::Type Pack(::Whms::Vec2::In InTexCoord)
            {

            }

            ::Whms::Void::Type Unpack(::Whms::Vec2::Out OutTexCoord)
            {

            }

            template<class OutT>
            ::Wiz::Size::Type CopyTo(OutT* DestPtr) const
            {
                WIZ_ASSERT(sizeof(this->e) == sizeof(tElement) * eCount);

                return ::Wiz::Memory::CopySrcStd(DestPtr, this->e, eCount);
            }
            template<class InT>
            ::Wiz::Size::Type CopyFrom(const InT* SrcPtr) const
            {
                WIZ_ASSERT(sizeof(this->e) == sizeof(tElement) * eCount);

                return ::Wiz::Memory::CopyDestStd(this->e, SrcPtr, eCount);
            }
        };
        WIZ_DECLARE(::Whms::PackedTexCoord::Type);
    } /// end of namespace PackedTexCoord
    ///==============================================================///
    namespace BoneInfluenceWeights
    {
        typedef ::Wiz::Vector4::Type<::Wiz::UInt8::Type>  ____;
        WIZ_DECLARE(::Whms::BoneInfluenceWeights::____);
    } /// end of namespace BoneInfluenceWeights
    ///==============================================================///
    namespace BoneInfluenceIndices
    {
        typedef ::Wiz::Vector4::Type<::Wiz::UInt8::Type>  ____;
        WIZ_DECLARE(::Whms::BoneInfluenceIndices::____);
    } /// end of namespace BoneInfluenceIndices
    ///==============================================================///

    namespace Trace
    {
        namespace Info
        {
            typedef ::Wiz::SP::Trace::Info::Type Type;
        } /// end of namespace Info

        namespace Result
        {
            template<class DataT>
            struct Type :
                public ::Wiz::SP::Trace::Result::Type
                <
                ::Whms::Real::Type,
                ::Whms::Vec3::Type,
                ::Whms::Vec3::Type,
                DataT
                >
            {

            };
        } /// end of namespace Result
    } /// end of namespace Trace

    namespace Kdtree
    {
        namespace Location
        {
            template<::Wiz::UInt::Type IMaxWorldSize   = 512 * 1024>
            struct Type : public ::Whms::Vec3::Type
            {
                typedef ::Whms::Vec3::Type  tSuper;
                typedef Type                tThis;
                Type() : m_MortonCode(0)
                {}
                Type(const tElement& InX, const tElement& InY, const tElement& InZ) : tSuper(InX, InY, InZ)
                {
                    CalcMortonCode();
                }

                Type(const tElement& InEle) : tSuper(InEle)
                {
                    CalcMortonCode();
                }

                Type(const tSuper& InOther) : tSuper(InOther)
                {
                    CalcMortonCode();
                }

                Type(const tThis& InOther) : tSuper(InOther), m_MortonCode(InOther.m_MortonCode)
                {
                }
                WIZ_INLINE tThis& operator=(const tSuper& InVec)
                {
                    this->x = InVec.x;
                    this->y = InVec.y;
                    this->z = InVec.z;

                    CalcMortonCode();

                    return *this;
                }
                ::Whms::Void::Type CalcMortonCode()
                {
                    static ::Whms::Real::TypeConst MinWorldSize = -(IMaxWorldSize >> 1);
                    static ::Whms::Real::TypeConst MaxWorldSize =  (IMaxWorldSize >> 1);

                    m_MortonCode = ::Wiz::MortonCode3D::Calc(x, y, z, MinWorldSize, MaxWorldSize);
                }

                WIZ_INLINE ::Wiz::UInt64::Type operator[](::Wiz::UInt::In i)
                {
                    return m_MortonCode;
                }
                WIZ_INLINE ::Wiz::UInt64::Type operator[](::Wiz::UInt::In i) const
                {
                    return m_MortonCode;
                }

                ::Wiz::UInt64::Type m_MortonCode;
            };
        } /// end of namespace Location

        template
            <
                class               DataT,
                ::Wiz::UInt::Type   IMaxDepth       = 32, 
                ::Wiz::UInt::Type   IMaxWorldSize   = 512 * 1024,
                class               BaseT           = ::Wiz::Null::Type
            >
        struct Type :
            public ::Wiz::Kdtree::Type
            <
            3,
            IMaxDepth,
            ::Whms::Kdtree::Location::Type<IMaxWorldSize>,
            DataT,
            ::Whms::Box::Type,
            ::Whms::Trace::Result::Type<DataT>,
            ::Wiz::Real::Type,
            IMaxWorldSize,
            BaseT
            >
        {
            typedef ::Wiz::Kdtree::Type
                <
                3,
                IMaxDepth,
                ::Whms::Kdtree::Location::Type<IMaxWorldSize>,
                DataT,
                ::Whms::Box::Type,
                ::Whms::Trace::Result::Type<DataT>,
                ::Wiz::Real::Type,
                IMaxWorldSize,
                BaseT
                >                                           tSuper;

            Type() : tSuper()
            {

            }

            Type(tLocationIn InLoc) : tSuper(InLoc)
            {

            }
        };
    } /// end of namespace Kdtree
} /// end of namespace Whms

#endif /*__WHIMSY_DATATYPE_HPP__SHANHAOBO_19800429__*/
